package datamining;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

public class Apriori
{
    private String[] data = null;
    private ArrayList<ItemSet[]> iterations = null;
    private ItemSet[] itemSets = null;
    private int itemSetDegree = 0;
    private int MIN_SUPPORT;
    private ArrayList<String> items;
    private Comparator<ItemSet> compare = new ItemSetComparator();

    public Apriori(String[] data, int minSupport)
    {
        MIN_SUPPORT = minSupport;
        this.data = data;
        items = new ArrayList();
        iterations = new ArrayList();
    }

    public void Apriorize(int courses)
    {
        InitializeItems();
        InitializeSets();
        CountInstances();
        for (int i = 1; i < courses; ++i)
        {
            RefreshSets();
            CountInstances();
        }
        
        PrintResults();
    }


    private void InitializeItems()
    {
        for (int i = 0; i < data.length; i++)
        {
            String phrase = data[i];
            String delims = "[ ]+";
            String[] words = phrase.split(delims);
            for (int j = 0; j < words.length; j++)
            {
                if (!items.contains(words[j]))
                {
                    items.add(words[j]);
                }
            }
        }
    }

    private void InitializeSets()
    {
        itemSets = new ItemSet[items.size()];
        for (int i = 0; i < items.size(); i++)
        {
            itemSets[i] = new ItemSet(items.get(i));
        }
        Arrays.sort(itemSets, compare);
        itemSetDegree++;
    }

    /*
     * Creates the item sets of itemSetDegree + 1 using the F_k-1 X F_k-1 -method.
     */
    private void RefreshSets()
    {
        //iterations.add(itemSets);

        ArrayList<ItemSet> newSets = new ArrayList();
        
        for (int i = 0; i < itemSets.length; ++i)
        {
            for (int j = 0; j < itemSets.length; ++j)
            {
                if (itemSets[i].getCount() >= MIN_SUPPORT && itemSets[j].getCount() >= MIN_SUPPORT)
                {
                    boolean isOk = true;
                    if (i == j)
                            isOk = false;
                    else
                    {
                        for (int k = 0; k < itemSets[i].getElements().length - 1; ++k)
                        {
                            if (!itemSets[i].getElements()[k].equals(itemSets[j].getElements()[k]))
                            {
                                isOk = false;
                                break;
                            }
                        }
                    }
                    if(isOk)
                    {
                        String[] tmp = new String[itemSetDegree + 1];
                        for (int k = 0; k < itemSetDegree-1; ++k)
                        {
                            tmp[k] = itemSets[i].getElements()[k];
                        }
                        tmp[itemSetDegree-1] = itemSets[i].getElements()[itemSetDegree-1];
                        tmp[itemSetDegree] = itemSets[j].getElements()[itemSetDegree-1];
                        newSets.add(new ItemSet(tmp));
                    }
                }
            }
        }
        itemSets = new ItemSet[newSets.size()];
        for (int i = 0; i < newSets.size(); i++)
        {
            itemSets[i] = newSets.get(i);
        }
        Arrays.sort(itemSets, compare);
        itemSetDegree++;
    }

    /*
     * Gives to an itemset one count more, if an itemset encounters the words that it contains in correct order at data row i.
     */
    private void CountInstances()
    {
        for (int i = 0; i < data.length; i++)
        {
            String phrase = data[i];
            String delims = "[ ]+";
            String[] words = phrase.split(delims);
            
            for (int j = 0; j < itemSets.length; ++j)
            {
                boolean found = false;
                String[] set = itemSets[j].getElements();
                int setIterator = 0;

                for (int k = 0; k < words.length; ++k)
                {
                    String tmptmp = set[setIterator];
                    if (words[k].equals(tmptmp))
                    {
                        setIterator++;
                        if (setIterator == set.length)
                        {
                            found = true;
                            break;
                        }
                    }
                }
                if (found == true)
                {
                    itemSets[j].addOneCount();
                }
            }
        }
    }

    private void PrintResults()
    {
        for (int i = 0; i < itemSets.length; ++i)
        {
            if (itemSets[i].getCount() != 0)
            {
                System.out.println(itemSets[i].toString() + ": " + itemSets[i].getCount());
            }
        }
        System.out.println("TOTAL AMOUNT: " + itemSets.length);
    }
}